Vue 组件数据传递问题总结

一、组件传值

1、父子组件

在一个组件中引入令一个组件,被引入的组件就是子组件,外面的是父组件。

当子组件想要使用父组件中的数据,父组件传过来的数据子组件用 props 属性来获取。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 父组件
<template>
<div class="father">
<child :msg = "test"/> // 向自组件传递数据
</div>
</template>
<script>
import child from XXX
export default {
name: 'Father',
components: {
child
},
data () {
return {
test: 'yin'
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
// 子组件
<template>
<div id="child">
{{msg}}
</div>
</template>
<script>
export default {
name: 'Child',
props: [
'msg' // 自组件获取父组件中的数据
]
}

2、子父组件

有时候父组件也想要子组件中的数据,这时子组件通过\$emit(事件名字,数据)触发事件来传递数据,父组件通过$on(事件名字,数据) 监听事件来接受数据。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// 父组件
<template>
<div id="father">
<child @show-msg="get_data"/> // 这里监听事件,监听到后调用 get_data 方法
{{msg}}
</div>
</template>
<script>
import child from XXX
export default {
name: 'Father',
components: {
child
},
data: function() {
return {
msg: ''
}
},
methods: {
get_data: function(data) {
this.msg = data.a;
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 子组件
<template>
<div id="child">
<button @click="set_data()">点击</button> // 点击时候调用 set_data 方法
</div>
</template>
<script>
export default {
name: 'Child',
methods: {
set_data: function() { // set_data 方法用$emit方法触发事件传递数据
this.$emit('show-msg', {a: 1,b: 2});
}
}
}

3、兄弟组件

两个组件互不引用就是兄弟组件。这时要用到一个事件调度器(一个空的 Vue 实例),在要传数据的组件中调度器通过Event.\$emit()触发事件,在要接受数据的组件中用调度器用Event.$on()监听数据。

1
2
3
4
5
6
7
8
9
...
<div id="app">
<brother1/>
<brother2/>
</div>
...
new Vue({
el: '#app'
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
var Event = new Vue() // 创建一个事件调度器

Vue.component('brother1', {
template: `
<div>she said<input v-model="she" @keyup="on_change"/> {{she}}</div>
`,
data: function() {
return {
she: ''
}
},
methods: {
on_change: function() {
Event.$emit('you-look',this.she); //触发事件
}
}
});

Vue.component('brother2', {
template: `
<div>I know {{me}}</div>
`,
data: function() {
return {
me: ''
}
},
mounted: function() {
var _this = this;
Event.$on('you-look', function(data) { // 监听事件
_this.me = data;
});
}
});

二、路由跳转

当通过切换路由由一个组件进入另一个组件的时候,有时候会获取当前路由中的一些参数,在 Vue 实例内部,你可以通过\$router访问路由实例,而路由实例上的 params 或者 query 属性就可以获取当前路由路径中的参数,具体用哪个要看路由跳转时用的哪个。所以我们根据路由的跳转情况来分析一下。

1、router.push(location, onComplete?, onAbort?)

想要导航到不同的 URL 就使用 router.push 方法。这个方法会向 history 栈添加一个新的记录,所以当用户点击浏览器后退按钮时,就回到了之前的 URL。当你点击 <router-link> 时,这个方法会在内部调用,所以点击 <router-link :to="..."> 等同于调用 router.push(...)

声明式 编程式
router.push(…)
1
2
3
4
5
6
7
8
// 字符串
router.push('home')
// 对象
router.push({ path: 'home' })
// 命名的路由
router.push({ name: 'user', params: { userId: 123 }})
// 带查询参数,变成 /register?plan=private
router.push({ path: 'register', query: { plan: 'private' }})

注意:如果提供了 path,params 会被忽略,上述例子中的 query 并不属于这种情况。取而代之的是下面例子的做法,你需要提供路由的 name 或手写完整的带有参数的 path:

1
2
3
4
5
const userId = 123
router.push({ name: 'user', params: { userId }}) // -> /user/123
router.push({ path: `/user/${userId}` }) // -> /user/123
// 这里的 params 不生效
router.push({ path: '/user', params: { userId }}) // -> /user

2、router.replace(location, onComplete?, onAbort?)

router.push 很像,唯一的不同就是,它不会向 history 添加新记录,而是替换掉当前的 history 记录。

声明式 编程式
router.replace(…)

3、router.go(n)

这个方法的参数是一个整数,意思是在 history 记录中向前或者后退多少步,类似 window.history.go(n)。

1
2
3
4
5
6
7
8
9
10
11
12
// 在浏览器记录中前进一步,等同于 history.forward()
router.go(1)

// 后退一步记录,等同于 history.back()
router.go(-1)

// 前进 3 步记录
router.go(3)

// 如果 history 记录不够用,那就默默地失败呗
router.go(-100)
router.go(100)

在浏览器中的符号#,以及#后面的字符称为hash,用window.location.hash读取。特点:hash虽然在url中,但是不被包括在HTTP的请求中,用来指导浏览器的动作,对服务器端安全无用,hash不会重载页面。

三、vuex

当需要在多个组件之间共享一些数据时用 vuex 为 vue 实现状态管理,避免多次请求重复数据。这里知道数据网这里存和要使用的时候怎么拿就行,特别要注意的就是页面刷新数据丢失问题,用 sessionStorage 解决即可。

微信打赏